import {AxdrType} from "./AxdrType";
import {ReverseByteArrayOutputStream} from "../ReverseByteArrayOutputStream";
import {AxdrBoolean} from "./AxdrBoolean";
import {ReverseByteArrayInputStream} from "../ReverseByteArrayInputStream";


export class AxdrOptional<T extends AxdrType> {

    value: T | null = null;
    usage: boolean = false;


    constructor(value: T, usage: boolean) {
        if (value == null) {
            throw new Error("Value cannot be null");
        }
        this.value = value;
        this.usage = usage;
    }

    decode(input : ReverseByteArrayInputStream) : number{
        let codeLength = 0;
        let axdrUsage = new AxdrBoolean();
        codeLength += axdrUsage.decode(input);
        this.usage = axdrUsage.getVal();
        if (this.usage) {
            codeLength += this.value.decode(input);
        }
        return codeLength;
    }

    encode(output: ReverseByteArrayOutputStream): number {
        let codeLength = 0;
        if (this.usage) {
            if(this.value != null){
                codeLength += this.value.encode(output);
            }else{
                throw new Error("value is null")
            }
        }
        let usage = new AxdrBoolean();
        usage.set_Val(this.usage);
        codeLength += usage.encode(output);
        return codeLength;
    }

    setUsed(use: boolean) {
        this.usage = use;
    }

    isUsed() {
        return this.usage;
    }

    getValue(): T {
        if (this.value != null) {
            return this.value;
        } else {
            throw new Error("value is null");
        }
    }

    setValue(value: T) {
        this.usage = this.value != null;
        if (this.value != null) {
            this.value = value;
        }
    }

    toString() : string{
        if (this.usage) {
            if(this.value != null){
                return this.value.toString();
            }else{
                throw new Error("value is null")
            }
        } else {
            return "not set";
        }
    }
}
